package com.sd.sdk.client;

import com.sd.sdk.core.bean.ApiReq;
import com.sd.sdk.core.bean.ApiResp;
import com.sd.sdk.core.exception.ApiErrorException;
import com.sd.sdk.core.exception.ApiException;
import com.sd.sdk.core.exception.ApiSingException;
import com.sd.sdk.core.utils.ApiDesEdeUtil;
import com.sd.sdk.core.utils.ApiMD5Util;

import javax.crypto.SecretKey;

/**
 * api客户端
 *
 * @author xy
 */
public class ApiClient {
    /** url */
    private final String baseUrl;
    /** 机构码key */
    private final String sourceKey;
    /** DESEde算法的密钥 */
    private static final String KEY3_DES = "C205BC5839533270jUN1d77Y";
    /** 密钥对象 */
    private static final SecretKey KEY = ApiDesEdeUtil.getKey(KEY3_DES);

    /**
     * api客户端 线上环境
     * @param sourceKey 机构码key
     */
    public ApiClient(String sourceKey) {
        this.sourceKey = sourceKey;
        baseUrl = "http://h5.schengle.com/";
    }

    /**
     * api客户端
     * @param sourceKey 机构码key
     * @param env 环境，test表示测试环境，其它表示线上
     */
    public ApiClient(String sourceKey, String env) {
        this.sourceKey = sourceKey;
        if ("test".equals(env)) {
            baseUrl = "http://h5-test.schengle.com/";
        } else {
            baseUrl = "http://h5.schengle.com/";
        }
    }

    /**
     * 执行接口调用
     * @param req 接口
     * @param <T> 返回值
     * @return 返回值，可能为null
     */
    public <T> T execute(ApiReq<T> req) {
        try {
            // 1 处理参数，发送请求，得到响应
            String result = HttpUtil.post(baseUrl + req.getUrl(), paramHandle(JsonUtil.toJson(req)));
            // 2 解析响应
            ApiResp apiResp = JsonUtil.toObject(result, ApiResp.class);
            // 2.1 SCCESS表示成功
            if (!"SUCCESS".equals(apiResp.getResultCode())) {
                throw new ApiErrorException(apiResp.getResultDes());
            }
            // 2.2 无加密数据或定义了不需要返回数据则返回null
            if (apiResp.getEncryptJsonStr() == null || req.getRespClass() == Void.class) {
                return null;
            }
            // 3 存在加密数据则解密
            String decrypt = ApiDesEdeUtil.decrypt(apiResp.getEncryptJsonStr(), KEY);

            // 4 |分割，前面的是响应参数，后面的是签名
            int endIndex = decrypt.lastIndexOf("|");
            String substring = decrypt.substring(0, endIndex);
            String sign = decrypt.substring(endIndex + 1);
            // 4.1 验签
            if (!verify(substring, sign)) {
                throw new ApiSingException();
            }

            // 5 解析返回值
            return JsonUtil.toObject(substring, req.getRespClass());
        } catch (ApiException e) {
            throw e;
        } catch (Exception e) {
            throw new ApiException("接口调用异常", e);
        }
    }

    /**
     * 提前参数处理
     * @param params 参数
     * @return 处理完毕的参数
     */
    private String paramHandle(String params) {
        String digest = ApiMD5Util.digest(params + sourceKey);
        String encrypt = ApiDesEdeUtil.encrypt(params + "|" + digest, KEY);
        return "{\"encryptJsonStr\":\"" + encrypt + "\"}";
    }

    /**
     * 验签
     * @param params 响应参数
     * @param sign 签名
     * @return true表示验证成功
     */
	 public boolean verify(String params, String sign) {
	        String paramSign = ApiMD5Util.digest(params + sourceKey);
	        return sign.equals(paramSign);
     }

}
